package com.xiaominfo.oss.utils;


import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Pattern;

/**
 * @Author lien
 * @Date 2019/12/24 16:52
 * @Description 文件操作工具类
 **/
public class FileUtils {

    public static final int KB_SIZE = 1024;
    public static final int MB_SIZE = 1024 * KB_SIZE;
    public static final int GB_SIZE = 1024 * MB_SIZE;


    /**
     * 设置文件不可修改
     * @param file
     */
    public static void fileUnModified(File file){
        if (file!=null){
            file.setWritable(false);
            file.setExecutable(false);
            file.setReadOnly();
        }
    }


    /***
     * 获取文件大小
     * @param file
     * @return
     */
    public static long getFileSize(File file){
        long size=0L;
        if (file.exists()){
            if (!file.isDirectory()){
                size=file.length();
            }else{
                size+=getDirSize(file);
            }
        }
        return size;
    }


    /**
     * 获取目录大小
     * @param file
     * @return
     */
    public static long getDirSize(File file){
        long dirsize=0l;
        if (file!=null){
            if (file.exists()){
                if (file.isDirectory()){
                    File[] files=file.listFiles();
                    for (File fl:files){
                        if (fl.isDirectory()){
                            dirsize+=getDirSize(fl);
                        }else{
                            dirsize+=fl.length();
                        }
                    }
                }
            }
        }
        return dirsize;
    }

    /***
     * byte字节转换为字符串
     * @param fileBytes
     * @return
     */
    public static String byteToString(long fileBytes){
        StringBuffer byteStr=new StringBuffer();
        BigDecimal fullSize=new BigDecimal(fileBytes);
        //mb
        BigDecimal mbSize=new BigDecimal(MB_SIZE);
        float gbsize=fullSize.divide(new BigDecimal(GB_SIZE),2,BigDecimal.ROUND_HALF_UP).floatValue();
        if (gbsize>1){
            byteStr.append(gbsize).append("GB");
        }else{
            float dvsize=fullSize.divide(mbSize,2,BigDecimal.ROUND_HALF_UP).floatValue();
            if (dvsize>1){
                byteStr.append(dvsize).append("MB");
            }else{
                //kb显示
                BigDecimal kbSize=new BigDecimal(KB_SIZE);
                byteStr.append(fullSize.divide(kbSize,2,BigDecimal.ROUND_HALF_UP).floatValue()).append("KB");
            }
        }
        return byteStr.toString();
    }

    /**
     * 获取文件类型
     * @param file
     * @return
     */
    public static String getFileType(File file){
        String type="文件";
        if (file.isDirectory()){
            type="文件夹";
        }else{
            String fileName=file.getName();
            //判断是否有后缀
            if (StrUtil.isNotBlank(fileName)){
                if (fileName.contains(".")){
                    String suffix=fileName.substring(fileName.lastIndexOf(".")+1);
                    type=suffix.toUpperCase()+" 文件";
                }
            }
        }
        return type;
    }

    /**
     * 获取文件到媒体类型
     * @param file
     * @return
     */
    public static String getMediaType(File file){
        String mediaType="text";
        if (file.isDirectory()){
            mediaType="dir";
        }else{
            String fileName=file.getName();
            //判断是否有后缀
            if (StrUtil.isNotBlank(fileName)){
                if (fileName.contains(".")){
                    String suffix=fileName.substring(fileName.lastIndexOf(".")+1);
                    mediaType=suffix.toLowerCase();
                }
            }
        }
        return mediaType;
    }


    /**
     * 获取操作系统的文件分隔符
     * @param path
     * @return
     */
    public static String transforSysSpec(String path){
        //获取操作系统
        String regex=".*?window.*";
        String nPath="";
        if (ReUtil.isMatch(Pattern.compile(regex,Pattern.CASE_INSENSITIVE),System.getProperty("os.name"))){
            //如果是windows
            nPath=path.replaceAll("\\\\","/");
        }else{
            nPath=path;
        }
        return nPath;
    }


    /**
     * 获取文件对象的md5
     * @param file
     * @return
     * @throws Exception
     */
    public static String getMd5ByFile(File file){
        try {
            // 拿到md5工具
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            // 拿到文件流
            FileInputStream in = new FileInputStream(file);
            // 读取文件的缓存
            byte[] buffer = new byte[1024 * 1024];
            int len = 0;
            while((len = in.read(buffer)) > 0) {
                // 利用md5工具对象更新好数据
                md5.update(buffer,0, len);
            }
            in.close();
            // 拿到MD5值字节数据
            byte[] bytes = md5.digest();
            // 将其转换为MD5字符串
            return bytesToHex(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 获取文件流对象的md5
     * @param in
     * @return
     */
    public static String getMd5ByStream(InputStream in){
        try {
            // 拿到md5工具
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            // 拿到文件流
            // 读取文件的缓存
            byte[] buffer = new byte[1024 * 1024];
            int len = 0;
            while((len = in.read(buffer)) > 0) {
                // 利用md5工具对象更新好数据
                md5.update(buffer,0, len);
            }
            in.close();
            // 拿到MD5值字节数据
            byte[] bytes = md5.digest();
            // 将其转换为MD5字符串
            return bytesToHex(bytes);
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            if(in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 用来做16进制转换
     */
    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    /**
     * 将字节数组转换为字符串
     * @param bytes 字节数组
     * @return      转换后的字符串
     */
    public static String bytesToHex(byte[] bytes) {
        // 一个byte为8位，可用两个十六进制位标识
        char[] buf = new char[bytes.length * 2];
        int index = 0;
        for(byte b : bytes) { // 利用位运算进行转换
            buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
            buf[index++] = HEX_CHAR[b & 0xf];
        }

        return new String(buf);
    }





    public static void main(String[] args) {
        File file=new File("D:\\无标题.xls");
        System.out.println(getFileType(file));
        System.out.println(getFileSize(file));
        System.out.println(byteToString(getDirSize(file)));
        System.out.println(System.getProperty("os.name"));
    }



}
